package com.wuzhun.wxmp.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wuzhun.wxmp.common.ResultCode;
import com.wuzhun.wxmp.common.ServiceException;
import com.wuzhun.wxmp.model.entity.Message;
import com.wuzhun.wxmp.model.entity.Wechat;
import com.wuzhun.wxmp.service.IMessageService;
import com.wuzhun.wxmp.service.IWechatService;
import com.wuzhun.wxmp.util.DateTimeUtil;
import com.wuzhun.wxmp.util.IpUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 用户登录Token表 前端控制器
 * </p>
 *
 * @author renbaolin
 * @since 2022-12-05
 */
@Slf4j
@RestController
@RequestMapping("/wechat/{appId}")
public class WechatController {
    @Resource
    private WxMpService wxService;
    @Resource
    private WxMpMessageRouter messageRouter;
    @Resource
    private IMessageService messageService;
    @Resource
    private IWechatService wechatService;

    @Value("${upload.file.path}")
    private String uploadPath;
    /**
     * 素材消息类型
     */
    public static final List<String> MATERIAL_LIST = Arrays.asList("video", "image", "voice");

    @GetMapping()
    public String authGet(@PathVariable String appId,
                          @RequestParam(name = "signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr) {

        log.info("authGet wechat request ：[{}, {}, {}, {}]", signature,
                timestamp, nonce, echostr);
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new ServiceException(ResultCode.PARAM_WRONG);
        }

        if (!this.wxService.switchover(appId)) {
            throw new ServiceException(ResultCode.SETTING_NOT_EXIST);
        }

        if (wxService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }
        return "非法请求";
    }

    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String postMessage(@PathVariable String appId,
                              @RequestBody String requestBody,
                              @RequestParam("signature") String signature,
                              @RequestParam("timestamp") String timestamp,
                              @RequestParam("nonce") String nonce,
                              @RequestParam("openid") String openid,
                              @RequestParam(name = "encrypt_type", required = false) String encType,
                              @RequestParam(name = "msg_signature", required = false) String msgSignature,
                              HttpServletRequest request) throws Exception {
        log.info("postMessage wechat request ：[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[{}] ",
                openid, signature, encType, msgSignature, timestamp, nonce, requestBody);

        if (!this.wxService.switchover(appId)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appId));
        }

        if (!wxService.checkSignature(timestamp, nonce, signature)) {
            throw new ServiceException(ResultCode.ERROR_SIGNATURE);
        }

        String out;
        WxMpXmlMessage inMessage = null;
        if (encType == null) {
            // 明文传输的消息
            inMessage = WxMpXmlMessage.fromXml(requestBody);
            log.info("postMessage accept message :{}", JSONObject.toJSONString(inMessage));
        } else if ("aes".equalsIgnoreCase(encType)) {
            // aes加密的消息
            inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxService.getWxMpConfigStorage(),
                    timestamp, nonce, msgSignature);
            log.info("postMessage accept aes message ：{} ", inMessage.toString());
        }
        if (inMessage == null) {
            return "";
        }
        // 取消关注不做处理
        if ("event".equals(inMessage.getMsgType()) && "unsubscribe".equals(inMessage.getEvent())) {
            return "";
        }
        String replyMessageText = "";
        Wechat wechat = wechatService.getOne(new QueryWrapper<Wechat>().eq("mp_id", inMessage.getToUser()));
        if (wechat != null) {
            if (StringUtils.isNotEmpty(wechat.getFlowReplyMessage()) && "event".equals(inMessage.getMsgType()) && "subscribe".equals(inMessage.getEvent())) {
                // 关注公众号自动回复
                replyMessageText = wechat.getFlowReplyMessage();
            } else {
                // 其他消息自动回复
                replyMessageText = wechat.getSendReplyMessage();
            }
        }
        Message message = new Message();
        String wxMessage = StringUtils.replace(inMessage.getContent(), "\n", "<br>");
        // 素材消息类型
        if(MATERIAL_LIST.contains(inMessage.getMsgType())) {
            File file = wxService.getMaterialService().mediaDownload(inMessage.getMediaId());
            File fileOut = new File(uploadPath + inMessage.getMsgType() + "/" + file.getName());
            FileCopyUtils.copy(file, fileOut);
            // 存储路径
            wxMessage = "/upload/" + inMessage.getMsgType() + "/" + file.getName();
            log.info("file:{}",file);
        }
        message.setWxUserId(inMessage.getFromUser());
        message.setMpId(inMessage.getToUser());
        message.setMsgType(inMessage.getMsgType());
        message.setMsgId(String.valueOf(inMessage.getMsgId()));
        message.setYear(String.valueOf(DateTimeUtil.getCurrentYear()));
        message.setIp(IpUtil.getIpAddress(request));
        log.info("postMessage save message :{}", JSONObject.toJSONString(message));
        if (StringUtils.isNotEmpty(wxMessage)) {
            message.setContent(wxMessage);
            messageService.save(message);
        }
        if (StringUtils.isEmpty(replyMessageText)) {
            log.info("wechat:{}", wechat);
            return "";
        }
        WxMpXmlMessage replyMessage = new WxMpXmlMessage();
        replyMessage.setFromUser(inMessage.getFromUser());
        replyMessage.setToUser(inMessage.getToUser());
        replyMessage.setMsgType("text");
        replyMessage.setContent(replyMessageText);
        replyMessage.setCreateTime(System.currentTimeMillis() / 1000);
        WxMpXmlOutMessage outMessage = this.route(replyMessage);
        if (outMessage == null) {
            log.info("postMessage replyMessage ：{}", replyMessage);
            return "";
        }
        out = outMessage.toXml();
        log.info("postMessage return message ：{}", out);
        return out;
    }

    private WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.messageRouter.route(message);
        } catch (Exception e) {
            log.error("route error : {}", e.getMessage());
        }
        return null;
    }
}
